简介
Painless
是一种简单、安全的脚本语言,专为与 Elasticsearch
一起使用而设计。它是 Elasticsearch
的默认脚本语言,可以安全地用于内联和存储脚本。
- 高性能:运行速度非常快;
- 安全性:具有方法调用/字段粒度的细粒度白名单;
- 变量和参数可以使用显示类型或动态的可变类型;
- 语法:扩展自
java
语法,使用方便; - 优化:专为
elasticsearch
设计
使用场景:script_score
、script_fields
、update_by_query
、update
、pipeline
以及 script
聚合等等。
使用方法
总的来说, painless
的语法与 java
基本一致,常规的条件判断 if
、for
循环、while
、新建对象 new
等用法都是一样的,下面主要记录了一些有区别,以及特殊的地方
取值方式
对 painless
来说,文档的数据一般存储在 ctx
、ctx._source
、doc
里,取值方式类似 javascript
的方式,通过 .fieldname
或者 ['fieldname']
取值均可。
根据常用的 API
,可以大致分为以下几个:
script_score
、script_field
、sort
、filter
等存储在doc
中,查询需要使用doc['field'].value
或者params['_source']['field']
来取值;_update_by_query
、reindex
等存储在ctx._source
中,需要使用ctx._source.field
取值;ingest pipeline
存储在ctx
中,直接使用ctx.field
取值;- 特例:
foreach processor
遍历处理器,需要使用_ingest._value
来取值
详情可参考 painless context, 需要注意的是 params['_source']['field']
这种取值方式在 painless
的文档中没有明确说明,需参考在 script_fields 中的说明
关键词
if | else | while | do | for |
---|---|---|---|---|
in | continue | break | return | new |
try | catch | throw | this | instanceof |
for循环
for
循环既可以使用普通的fori
循环也可以使用for(int i : xxx)
这种语法糖;获取数组长度时,使用
.length
和.size()
两种取值方式均可
日期操作
painless
会将 mapping
映射为 date
类型的字段当做 zonedateTime
来处理,因此支持 getYear
,getDayOfWeek
,getMillis
等操作,但在编写脚本时,省略掉了 get
前缀,只需要小写方法名称的其余部分,例如:1
2
3
4
5
6
7
8
9
10GET hockey/_search
{
"script_fields": {
"birth_year": {
"script": {
"source": "doc.born.value.year + ',' + doc.born.value.monthValue"
}
}
}
}
正则表达式
出于正则表达式的性能原因,painless
中默认是禁用了的,需要在配置文件中开启:1
script.painless.regex.enabled: true
使用正则时需要以 /
符号作为正则的起始和结束标志,正则表达式写在斜线的中间部分,列如,匹配字符串是否以 b
开头:
1 | POST hockey/_update_by_query |
额外的动态类型 def
1 | def dp = 1; |
painless 函数声明及运作方式
以 s.foo(a,b)
调用为例,painless
在执行时会先获取到类 s 然后查找带有两个参数以及方法名为 foo
的方法进行调用,这种方式使得 painless
不像 java
那样支持重载,列如 java
中的 Matcher
类有两个方法 group(int)
和 group(String)
,由于他们的参数数量和方法名都相同,painless
将无法分辨,所以 painless
中使用 group(int)
和 namedGroup(String)
两个方法来进行区分
函数声明:
在调用方法前声明函数即可,在 painless
中的 String
类是不具备 split
函数的,如下的示例展示了一个自定义的 split 和使用方式:
1 | POST index_a/_doc |
支持的API
painless
中支持的 API
可参考这个地址